package org.example.web;

import com.fj.redisson.annotation.ConcurrencySafe;
import org.example.web.model.RequestModel;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

/**
 * @author fj
 * @date 2023/12/27 14:21
 */
@ControllerAdvice
@RestController
@RequestMapping("red")
public class RedissonController {

    @Autowired
    private RedissonClient redisson;

    @GetMapping("test1/{orderId}")
    public ResponseEntity test1(@PathVariable String orderId){
        Assert.notNull(orderId);
        RLock lock = redisson.getLock("lock_" + orderId);
        boolean b = false;
        try {
            b = lock.tryLock(8, 20, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if (b){
            System.out.println(orderId+"_"+Thread.currentThread().getName()+"获取锁...");
            try {
                Thread.sleep(5000);
                System.out.println(orderId+"_"+Thread.currentThread().getName()+" doing...");
                return ResponseEntity.ok("success");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
//        RBucket<String> bucket = redisson.getBucket("1");
        System.out.println(orderId+"_"+Thread.currentThread().getName()+"失败");
        return ResponseEntity.ok("fail");
    }

    @ConcurrencySafe(objClass = RequestModel.class,fields = {"orderId","status"},waitTime = 8000)
    @RequestMapping(value = "test2")
    public ResponseEntity test2(RequestModel model) throws Exception{
        System.out.println(model);
        TimeUnit.SECONDS.sleep(5);
        System.out.println(Thread.currentThread().getName()+" doing...");
        return ResponseEntity.ok("test2");
    }

    @ExceptionHandler
    public ResponseEntity exceptionHandler(Throwable throwable) throws Throwable{
        if (throwable instanceof RuntimeException && throwable.getMessage().equals("加锁失败")){
            return ResponseEntity.internalServerError().body("重复通知");
        }
        throw throwable;
    }
}
